package br.org.acessobrasil.portal.facade;

import java.util.List;

import javax.persistence.Query;

import org.apache.log4j.Logger;

import br.org.acessobrasil.facade.FacadeException;
import br.org.acessobrasil.facade.GenericFacade;
import br.org.acessobrasil.portal.modelo.ItemMenu;
import br.org.acessobrasil.portal.modelo.Menu;
import br.org.acessobrasil.portal.modelo.Pagina;
import br.org.acessobrasil.portal.modelo.Usuario;
import br.org.acessobrasil.portal.persistencia.LogDao;
import br.org.acessobrasil.portal.util.ListItem;

public class ItemMenuFacade extends GenericFacade<Usuario, ItemMenu> {
	private static Logger logger = Logger.getLogger(Logger.class);
	private LogDao logDao; 
	
	public LogDao getLogDao() {
		return logDao;
	}
	
	public void setLogDao(LogDao logDao) {
		this.logDao = logDao;
	}
	
	private PaginaFacade paginaFacade;
	
	public PaginaFacade getPaginaFacade() {
		return paginaFacade;
	}
	
	public void setPaginaFacade(PaginaFacade paginaFacade) {
		this.paginaFacade = paginaFacade;
	}
	
	/**
	 * Verifica o nuMenu e o link
	 * @param obj ItemMenu
	 * @throws FacadeException
	 */
	private void verificar(ItemMenu obj) throws FacadeException{
		if (obj.getNuMenu() == null){
			throw new FacadeException("Informe o nu_menu do item.");
		}
		if(obj.getNoLinkExterno()!=null){
			String link=obj.getNoLinkExterno().replace("&amp;","&").replace("&","&amp;");
			obj.setNoLinkExterno(link);
		}
	}
	
	public void criar(Usuario ator, ItemMenu obj) throws FacadeException {
		verificar(obj);
		super.criar(ator, obj);
		reordenar(obj.getNuMenu());
		logDao.addLog(ator, "Inseriu item de menu [id=" + obj.getNuItemMenu()+" titulo="+obj.getNoTitulo()+"]");
	}

	@Override
	public void excluir(Usuario ator, ItemMenu obj) throws FacadeException {
		super.excluir(ator, obj);
		reordenar(obj.getNuMenu());
		logDao.addLog(ator, "Excluiu item de menu [id=" + obj.getNuItemMenu()+" titulo="+obj.getNoTitulo()+"]");
	}
	
	public ItemMenu atualizar(Usuario ator, ItemMenu obj) throws FacadeException {
		verificar(obj);
		logDao.addLog(ator, "Atualizou item de menu [id=" + obj.getNuItemMenu()+" titulo="+obj.getNoTitulo()+"]");
		ItemMenu itemMenu = super.atualizar(ator, obj);
		itemMenu.setNuPagina(obj.getNuPagina());
		reordenar(obj.getNuMenu());
		return itemMenu;
	}
	
	/**
	 * Reordena os itens de menu para nao haver nuOrdem duplicado
	 * @param nu_menu - id do menu.
	 */
	@SuppressWarnings("unchecked")
	private void reordenar(Long nu_menu){	
		try {
			getEntityManager().flush();
			Query q = getEntityManager().createQuery("Select item From ItemMenu item where nu_menu = ? order by nu_ordem, nu_item_menu");
			q.setParameter(1, nu_menu);
			List<ItemMenu> listaItens = q.getResultList();
			for (int i = 0; i < listaItens.size(); i++) {
				listaItens.get(i).setNuOrdem(i + 1);
			}
		} catch (Exception e) {
			logger.error("Erro ao reordenar", e);
		}
	}
	
	/**
	 * Delegate para pagina facade
	 * @param nuSitio
	 * @return lista de paginas do sitio
	 */
	public List<Pagina> listarPaginas(Long nuSitio) throws FacadeException  {
		return paginaFacade.listar(nuSitio);
	}

	public Menu buscarMenu(Usuario usuarioLogado, Long nuMenu) throws FacadeException  {
		return getEntityManager().find(Menu.class, nuMenu);
	}
	
	@SuppressWarnings("unchecked")
	public List<ItemMenu> listarItensDeMenu(Usuario ator,Long nuMenu) throws FacadeException  {
		Query q = getEntityManager().createQuery("Select o from ItemMenu o where o.nu_menu=? order by nu_ordem, nu_item_menu");
		q.setParameter(1,nuMenu);
		List<ItemMenu> listaItemMenu = q.getResultList();
		return listaItemMenu;
	}

	/**
	 * Troca o nu_ordem com o item de ordem acima
	 * @param ator
	 * @param itemMenu
	 * @throws FacadeException
	 */
	public void aumentarOrdemItem(Usuario ator , ItemMenu itemMenu) throws FacadeException  {
		boolean alterado = false;
		itemMenu = getEntityManager().find(ItemMenu.class, itemMenu.getNuItemMenu());
		List<ItemMenu> list = listarItensDeMenu(ator, itemMenu.getNuMenu());
		for(int i=0;i<list.size();i++){
			ItemMenu item = list.get(i);
			if(item.getNuItemMenu().equals(itemMenu.getNuItemMenu())){
				if(i>0){
					ItemMenu itemAcima = list.get(i-1);
					item.setNuOrdem(itemAcima.getNuOrdem());
					itemAcima.setNuOrdem(itemAcima.getNuOrdem()+1);
					alterado = true;
				}else{
					throw new FacadeException("O item j&aacute; &eacute; o primeiro da lista.");
				}
				break;
			}
		}
		if(!alterado){
			throw new FacadeException("ItemMenu com id =  "+itemMenu.getNuItemMenu() +" nao alterado...");
		}
		getEntityManager().flush();
		logDao.addLog(ator, "Alterou ordem para cima do item de menu [id=" + itemMenu.getNuItemMenu()+" titulo="+itemMenu.getNoTitulo()+"]");
	}

	/**
	 * Troca o nu_ordem com o item de ordem abaixo
	 * @param ator
	 * @param itemMenu
	 * @throws FacadeException
	 */
	public void diminuirOrdemItem(Usuario ator, ItemMenu itemMenu) throws FacadeException  {
		boolean alterado = false;
		itemMenu = getEntityManager().find(ItemMenu.class, itemMenu.getNuItemMenu());
		List<ItemMenu> list = listarItensDeMenu(ator, itemMenu.getNuMenu());
		for(int i=0;i<list.size();i++){
			ItemMenu item = list.get(i);
			if(item.getNuItemMenu().equals(itemMenu.getNuItemMenu())){
				if((i+1)<list.size()){
					ItemMenu itemAbaixo = list.get(i+1);
					item.setNuOrdem(itemAbaixo.getNuOrdem());
					itemAbaixo.setNuOrdem(itemAbaixo.getNuOrdem()-1);
					alterado = true;
				}else{
					throw new FacadeException("O item j&aacute; &eacute; o &uacute;ltimo da lista.");
				}
				break;
			}
		}
		if(!alterado){
			throw new FacadeException("ItemMenu com id =  "+itemMenu.getNuItemMenu() +" nao alterado...");
		}
		getEntityManager().flush();
		logDao.addLog(ator, "Alterou ordem para baixo do item de menu [id=" + itemMenu.getNuItemMenu()+" titulo="+itemMenu.getNoTitulo()+"]");
	}

	public void aumentarNivelItem(Usuario ator ,ItemMenu itemMenu) throws FacadeException  {
		itemMenu = buscar(ator, itemMenu.getNuItemMenu());
		itemMenu.setNuNivel(itemMenu.getNuNivel() + 1);
	}

	public void diminuirNivelItem(Usuario ator , ItemMenu itemMenu) throws FacadeException  {
		itemMenu = buscar(ator, itemMenu.getNuItemMenu());
		itemMenu.setNuNivel(itemMenu.getNuNivel() - 1);
	}

	public Pagina buscarPagina(Usuario usuarioLogado, Long nuPagina) throws FacadeException {
		return paginaFacade.buscar(usuarioLogado, nuPagina);
	}

	public List<Pagina> listarPaginasPorItemMenu(Long nuSitio, Long nuItemMenu) {
		return paginaFacade.listarPorItemMenu(nuSitio, nuItemMenu);
	}
	
	
}
